/* Copyright (c) 2004-2008, Andriy Nikolov
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.processmining.email;

import java.util.*;
import java.io.*;
import java.text.*;

/**
 * <p>Represents one e-mail message in the e-mail log
 *
 * @author Andriy Nikolov
 * @version 1.0
 */
public class EMailMessage implements TimestampOwner {
  String id = new String();
  EMailRecipient from;
  Vector to;
  Vector cc;
  Vector bcc;
  String subject = new String();
  String caseDescription = new String();
  String task = new String();
  String phase = new String();
  Date sentOn = new Date();
  boolean active;

  public EMailMessage() {
    to = new Vector(1);
    cc = new Vector(0);
    bcc = new Vector(0);
    active = true;
  }

  private boolean allFieldsFilled() {
    if (from.getName().length()==0) {
      return false;
    }
    if (to.isEmpty()&&cc.isEmpty()&&bcc.isEmpty()) {
      return false;
    }
    if (caseDescription.length()==0) {
      return false;
    }
    if (task.length()==0) {
      return false;
    }
    return true;
  }

  /**
   * Checks if the message is equal to another one
   *
   * @param message EMailMessage
   * @return boolean
   */
  public boolean isEqualTo(EMailMessage message) {
    if(message.getFrom()==null)return false;
    if (!message.getFrom().equals(from)) {
      return false;
    }
    if (message.getSubject()!=subject) {
      return false;
    }
    if (message.getTask()!=task) {
      return false;
    }
    if(message.getCase()!=caseDescription) {
      return false;
    }
    if(message.getPhase()!=phase) {
      return false;
    }
    if((to.size()!=message.getTo().size())||(!to.containsAll(message.getTo()))) {
      return false;
    }
    if((cc.size()!=message.getCc().size())||(!cc.containsAll(message.getCc()))) {
      return false;
    }
    if((bcc.size()!=message.getBcc().size())||(!bcc.containsAll(message.getBcc()))) {
      return false;
    }
    if(message.sentOn!=sentOn) {
      return false;
    }
    return true;
  }

  /**
   * sets the id of the message
   *
   * @param id String
   */
  public void setId(String id) {
    this.id = id;
  }

  /**
   * Gets the id of the message. Id of the message is usually equal to its
   * Outlook id.
   *
   * @return String
   */
  public String getId() {
    return id;
  }

  /**
   * Sets the sender of the message
   *
   * @param from EMailRecipient
   */
  public void setFrom(EMailRecipient from) {
    this.from = from;
    from.addMessage(this);
  }

  /**
   * Gets the sender of the message
   *
   * @return EMailRecipient
   */
  public EMailRecipient getFrom() {
    return from;
  }

  /**
   * Gets the list of message's recipients
   *
   * @return Vector
   */
  public Vector getTo() {
    return to;
  }

  /**
   * Adds a recipient to the list of messages recipients
   *
   * @param value EMailRecipient
   */
  public void addTo(EMailRecipient value) {
    to.add(value);
    value.addMessage(this);
  }

  /**
   * Gets the list of message's Cc recipients
   *
   * @return Vector
   */
  public Vector getCc() {
    return cc;
  }

  /**
   * Adds a recipient to the list of messages Cc recipients
   *
   * @param value EMailRecipient
   */
  public void addCc(EMailRecipient value) {
    cc.add(value);
    value.addMessage(this);
  }

  /**
   * Gets the list of message's Bcc recipients
   *
   * @return Vector
   */
  public Vector getBcc() {
    return bcc;
  }

  /**
   * Adds a recipient to the list of messages Bcc recipients
   *
   * @param value EMailRecipient
   */
  public void addBcc(EMailRecipient value) {
    bcc.add(value);
    value.addMessage(this);
  }

  /**
   * Sets the message subject
   *
   * @param subject String
   */
  public void setSubject(String subject) {
    this.subject = subject;
  }

  /**
   * Gets the message subject
   *
   * @return String
   */
  public String getSubject() {
    return subject;
  }

  /**
   * Sets the name of the process case related to the message (if the message
   * was tagged intentionally)
   *
   * @param caseDescription String
   */
  public void setCase(String caseDescription) {
    this.caseDescription = caseDescription;
  }

  /**
   * Gets the name of the process case related to the message (if the message
   * was tagged intentionally)
   *
   * @return String
   */
  public String getCase() {
    return caseDescription;
  }

  /**
   * Sets the name of the process task related to the message (if the message
   * was tagged intentionally)
   *
   * @param task String
   */
  public void setTask(String task) {
    this.task = task;
  }

  /**
   * Gets the name of the process task related to the message (if the message
   * was tagged intentionally)
   *
   * @return String
   */
  public String getTask() {
    return task;
  }

  /**
   * Sets the name of the process task phase (e.g. "start" or "abort") related
   * to the message (if the message was tagged intentionally)
   *
   * @param phase String
   */
  public void setPhase(String phase) {
    this.phase = phase;
  }

  /**
   * Gets the name of the process task phase (e.g. "start" or "abort") related
   * to the message (if the message was tagged intentionally)
   *
   * @return String
   */
  public String getPhase() {
    return phase;
  }

  /**
   * Sets the sent date of the message
   *
   * @param sentOn Date
   */
  public void setSentOn(Date sentOn) {
    this.sentOn = sentOn;
  }

  /**
   * Gets the sent date of the message
   *
   * @return Date
   */
  public Date getSentOn() {
    return sentOn;
  }

  /**
   * Gets the sent date of the message (the same as getSentOn())
   *
   * @return Date
   */
  public Date getTimestamp() {
    return sentOn;
  }

  /**
   * Checks if the message should be included into the further analysis
   *
   * @return boolean
   */
  public boolean isActive() {
    return active;
  }

  /**
   * Specifies if the message should be included into the further analysis
   *
   * @param value boolean
   */
  public void setActive(boolean value) {
    active = value;
  }

  /**
   * Checks if the message is linked to at least one sender/recipient, which is
   * not excluded from analysis
   *
   * @return boolean
   */
  public boolean hasActiveRecipients() {
    EMailRecipient tmp;
    tmp = from;
    if(!tmp.isActive())
      return false;
    for(int i=0;i<to.size();i++) {
      tmp = (EMailRecipient)to.get(i);
      if(tmp.isActive())
        return true;
    }
    for(int i=0;i<cc.size();i++) {
      tmp = (EMailRecipient)cc.get(i);
      if(tmp.isActive())
        return true;
    }
    for(int i=0;i<bcc.size();i++) {
      tmp = (EMailRecipient)bcc.get(i);
      if(tmp.isActive())
        return true;
    }
    return false;
  }

  /**
   * Writes the message content into the Writer. Used only by EMailLog objects
   *
   * @param writer PrintWriter
   */
  public void save(PrintWriter writer) {
    int i;
    EMailRecipient tmp;
    DateFormat df = DateFormat.getDateTimeInstance();

    writer.println("<Message messageId=\""+id+"\">");
    writer.print("<From>");
    writer.print(refineString(from.getName()));
    writer.println("</From>");
    for(i=0;i<to.size();i++) {
      writer.print("<To>");
      tmp = (EMailRecipient)to.get(i);
      writer.print(refineString(tmp.getName()));
      writer.println("</To>");
    }
    for(i=0;i<cc.size();i++) {
      writer.print("<Cc>");
      tmp = (EMailRecipient)cc.get(i);
      writer.print(refineString(tmp.getName()));
      writer.println("</Cc>");
    }
    for(i=0;i<bcc.size();i++) {
      writer.print("<Bcc>");
      tmp = (EMailRecipient)bcc.get(i);
      writer.print(refineString(tmp.getName()));
      writer.println("</Bcc>");
    }
    writer.print("<Subject>");
    writer.print(refineString(subject));
    writer.println("</Subject>");
    writer.print("<Case>");
    writer.print(refineString(caseDescription));
    writer.println("</Case>");
    writer.print("<Task>");
    writer.print(refineString(task));
    writer.println("</Task>");
    writer.print("<Phase>");
    writer.print(refineString(phase));
    writer.println("</Phase>");
    writer.print("<SentOn>");
    writer.print(df.format(sentOn));
    writer.println("</SentOn>");
    writer.println("</Message>");
  }

  private String refineString(String str) {
    String tmp = str;
    tmp = tmp.replaceAll("&", "&amp;");
    tmp = tmp.replaceAll("<", "&lt;");
    tmp = tmp.replaceAll(">", "&gt;");
    tmp = tmp.replaceAll("\"", "&quot;");
    tmp = tmp.replaceAll("\'", "&apos;");
    return tmp;
  }
}
